package org.tinygame.herostory;

import com.google.protobuf.GeneratedMessageV3;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelOutboundHandlerAdapter;
import io.netty.channel.ChannelPromise;
import io.netty.handler.codec.http.websocketx.BinaryWebSocketFrame;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.tinygame.herostory.msg.GameMsgProtocol;

/**
 * 自定义的消息编码器，继承了ChannelOutboundHandlerAdapter
 * 这是一个出站处理器
 */
public class GameMsgEncoder extends ChannelOutboundHandlerAdapter {
    private static final Logger LOGGER = LoggerFactory.getLogger(GameMsgEncoder.class);

    @Override
    public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
        //如果不是解码后的数据格式，直接调用原方法后返回，不做编码处理
        if (null == msg || !(msg instanceof GeneratedMessageV3)){
            super.write(ctx,msg,promise);
            return;
        }

        //根据协议获取msgCode
        int msgCode = GameMsgRecognizer.getMsgCodeByMsgClazz(msg.getClass());
        if (msgCode<=-1){
            LOGGER.error("无法识别的消息类型，msgClazz = " + msg.getClass().getName());
        }

        //根据协议中约定好的消息编号代码，调用不同的编码方法进行编码
        byte[] byteArray = ((GeneratedMessageV3) msg).toByteArray();

        ByteBuf byteBuf = ctx.alloc().buffer();//划分一块新的内存空间
        byteBuf.writeShort((short) 0);//写入消息长度,目前写入0只是为了占位
        byteBuf.writeShort((short) msgCode);//写入消息编号
        byteBuf.writeBytes(byteArray);//写入消息体

        //入站解码之前是BinaryWebSocketFrame类型的消息，所以出站编码时重新转为BinaryWebSocketFrame类型的消息
        BinaryWebSocketFrame frame = new BinaryWebSocketFrame(byteBuf);
        //调用netty的方法，让操作继续传递下去
        super.write(ctx,frame,promise);


    }
}
